import React, {useCallback, useEffect, useRef, useState} from "react"
import {
    addProcurementItem, convertProcurementToMarketOrder,
    deleteProcurementItem,
    deleteProcurementItemSub,
    downloadImportProcurementItemsTemplate,
    findAllGoodsWithHistoryProcurementSupplier,
    getProcurementDetail,
    importProcurementItemFromExcel,
    ProcurementDetail,
    ProcurementItem,
    receiptProcurement,
    submitProcurement,
    updateProcurementItemAmount,
    updateProcurementItemNote, updateProcurementItemPurchasePrice,
    updateProcurementItemSubAmount,
    updateProcurementItemSubNote, updateProcurementItemSubPurchasePrice,
    updateProcurementNote
} from "../../apis/ProcurementApi";
import {Button, Col, Descriptions, Input, message, Popover, Row, Space, Table, theme, Typography, Upload} from "antd";
import {OffsetDateTime} from "@js-joda/core";
import {
    convertAntdTableToExcelWithOptions,
    ExportedColumnProps,
} from "../../utils/AntdTableUtils";
import AuthorizationResource from "../../components/AuthorizationResource";
import {DeleteOutlined, EditOutlined, QuestionCircleOutlined, UploadOutlined} from "@ant-design/icons";
import DataPageLayout from "../../components/DataPageLayout";
import ArrayUtils from "@zxy-cn/array-utils";
import dashboardPageStore from "../../store/DashboardPageStore";
import {observerDashboardPageWrapper} from "./ObserverDashboardPageWrapper";
import employeeAuthorizationStore from "../../store/EmployeeAuthorizationStore";
import LoadableButton from "../../components/LoadableButton";
import {useNavigate} from "react-router";
import {Link} from "react-router-dom";
import EditOrderItemRow, {EditOrderItemGoodsData} from "../../components/EditOrderItemRow";
import {saveTo, saveWorkbookTo} from "../../utils/FileSaver";
import GoodsTable from "../../components/GoodsTable";
import EditAmountAndUnitPopover from "../EditAmountAndUnitPopover";
import {useLiveQuery} from "dexie-react-hooks";
import {GoodsAmountAndUnitUseHistoryScope, myDatabase} from "../../database/MyDatabase";
import {DATE_WITH_TIME_FORMATER} from "../../utils/Date";
import TableColumnSelectModal from "../TableColumnSelectModal";
import SingleInputPopover from "../SingleInputPopover";
import {types} from "sass";
import Number = types.Number;
import {useSubGoodsTableColumnConfiguration} from "../../utils/SubGoodsHooks";
import {MarketOrderItem} from "../../apis/MarketOrderApi";
import MarketSelectPopover from "../MarketSelectPopover";


export interface pageProps {
    id: number
}

const myPath = "procurements/{id}"

const ProcurementDetailPage: React.FC<pageProps> = ({id}) => {
    const [loading, setLoading] = useState(false)
    const [data, setData] = useState<ProcurementDetail>()
    const query = useCallback(() => {
        setLoading(true)
        getProcurementDetail(id).then(response => {
            dashboardPageStore.setTitle(myPath.replace("{id}", id.toString()), response.data.supplier.name + "采购单")
            setData(response.data)
        }).finally(() => {
            setLoading(false)
        })
    }, [id])

    useEffect(() => {
        query()
    }, [query]);

    let token = theme.useToken();

    let navigate = useNavigate();
    let columnsRef = useRef<ExportedColumnProps<ProcurementItem>[]>();

    let amountAndUnitHistories = useLiveQuery(() => {
        return myDatabase.goodsAmountAndUnitUseHistory.where({
            scope: GoodsAmountAndUnitUseHistoryScope.PROCUREMENT,
            resourceId: id,
        }).toArray()
    }, [id]);

    const [importing, setImporting] = useState(false)
    const [messageApi, contextHolder] = message.useMessage();

    const [openExportColumnSelectModal, setOpenExportColumnSelectModal] = useState(false)

    let configSubGoodsColumns = useSubGoodsTableColumnConfiguration<ProcurementItem>();
    const onUpdateNoteConfirm = useCallback(async value => {
        await updateProcurementNote(id, value)
        setData(({
            ...data!!,
            note: value,
        }))
    }, [data, id]);

    const tableSummaryGenerator = useCallback(() => {
        return <>
            <Table.Summary.Row>
                <Table.Summary.Cell index={0}>总零售金额</Table.Summary.Cell>
                <Table.Summary.Cell
                    index={1}>{ArrayUtils.sum(data?.items?.map(it => it.amountInOrder * it.price) ?? []).toFixed(2)}</Table.Summary.Cell>
                <Table.Summary.Cell index={2}>总采购价</Table.Summary.Cell>
                <Table.Summary.Cell
                    index={3}>{ArrayUtils.sum(data?.items?.map(it => it.amountInOrder * ((it.units.find(unit => unit.id === it.unit?.id)?.basicMultiple) || 1) * it.purchasePrice) ?? []).toFixed(2)}</Table.Summary.Cell>
                <>
                    <Table.Summary.Cell index={4}>备注</Table.Summary.Cell>
                    <Table.Summary.Cell index={5} colSpan={5}>
                        <Space>
                            <Typography.Text>{data?.note ? data.note : "无"}</Typography.Text>
                            {!!data &&
                                <SingleInputPopover initialValue={data.note}
                                                    title={`修改备注${data.items.length}`}
                                                    onConfirm={onUpdateNoteConfirm}
                                                    fieldName={"备注"}>

                                    <Button icon={<EditOutlined/>}
                                            type={"link"}
                                            onClick={() => {

                                            }}/>
                                </SingleInputPopover>}
                        </Space>
                    </Table.Summary.Cell>
                </>
            </Table.Summary.Row>
        </>
    }, [data,onUpdateNoteConfirm]);
    return (
        <>
            {contextHolder}
            {!loading ? <Descriptions title={"订单明细"}>
                <Descriptions.Item label={"供货商"}>{data?.supplier?.name}</Descriptions.Item>
                <Descriptions.Item label={"下单人"}>{data?.createdBy?.name}</Descriptions.Item>
                {!!data?.createdDateTime && <Descriptions.Item
                    label={"下单时间"}>{data?.createdDateTime.format(DATE_WITH_TIME_FORMATER)}</Descriptions.Item>}
                {!!data?.submittedDateTime && <Descriptions.Item
                    label={"提交时间"}>{data?.submittedDateTime.format(DATE_WITH_TIME_FORMATER)}</Descriptions.Item>}
                {!!data?.receiptDateTime ? <Descriptions.Item
                    label={"入库时间"}>{data.receiptDateTime.format(DATE_WITH_TIME_FORMATER)}</Descriptions.Item> : undefined}

            </Descriptions> : null}
            <Row gutter={8} style={{margin: "12px 0"}}>
                <Col>
                    {!data?.submittedDateTime && employeeAuthorizationStore.hasAuthority("采购_下单") ?
                        <Space size={4}>
                            <Upload fileList={[]}
                                    accept={"application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}
                                    maxCount={1}
                                    beforeUpload={file => {
                                        setImporting(true)
                                        importProcurementItemFromExcel(id, file).then(response => {
                                            if (response.data) {
                                                query();
                                                return messageApi.success(`成功导入${response.data}个货品`);
                                            } else {
                                                return messageApi.error(`无货品被导入，请检查格式是否正确`);
                                            }
                                        }).finally(() => {
                                            setImporting(false)
                                        });
                                        return false
                                    }}>
                                <Button icon={<UploadOutlined/>} loading={importing}>导入</Button>
                            </Upload>
                            <Popover title={"导入货品"} content={
                                <Typography>
                                    <Typography.Paragraph>
                                        按照约定的格式上传excel文件。
                                        <Typography.Link onClick={() => {
                                            downloadImportProcurementItemsTemplate().then(res => res.data)
                                                .then(blob => {
                                                    saveTo(blob, "导入采购订单模板.xlsx")
                                                })

                                        }}>下载模板</Typography.Link>
                                    </Typography.Paragraph>
                                    <Typography.Paragraph>
                                        <ul>
                                            <li>默认使用以前的采购价或者进价，如果都不存在则采购价为0</li>
                                            <li>相同的条码，和子商品编号会被忽略</li>
                                            <li>必填的属性未填会被忽略</li>
                                        </ul>
                                    </Typography.Paragraph>
                                </Typography>
                            }><QuestionCircleOutlined/></Popover>
                        </Space> : undefined}
                </Col>
                <Col>
                    <LoadableButton onClick={async (event) => {
                        event.stopPropagation()
                        setOpenExportColumnSelectModal(true)
                    }}>
                        导出
                    </LoadableButton>
                    <TableColumnSelectModal cacheKey={"procurement"}
                                            availableColumns={["条码", "名称", "子商品编号", "子商品名称", "数量与单位", "数量", "单位", "零售价", "采购单价", "备注"]}
                                            open={openExportColumnSelectModal} onConfirm={async fields => {
                        let columns = Array.from(columnsRef.current!!);
                        ArrayUtils.insertAfter(columns, value => value.dataIndex === "amountInOrder", {
                            dataIndex: "amountWithoutUnit",
                            title: "数量",
                            render: (_, record) => {
                                return record.amountInOrder
                            },
                        },)
                        ArrayUtils.insertAfter(columns, value => value.dataIndex === "amountWithoutUnit", {
                            dataIndex: "unit",
                            title: "单位",
                            render: (_, record) => {
                                return record.unit?.name
                            },
                        },)
                        let workbook = await convertAntdTableToExcelWithOptions(columns, data?.items ?? [], {
                            selectedColumns: fields, postHandler: worksheet => {
                                if (data?.note) {
                                    let nextRow = worksheet.getRow(worksheet.lastRow!!.number + 1);
                                    nextRow.getCell(1).value = "备注"
                                    nextRow.getCell(2).value = data.note
                                    worksheet.mergeCells(nextRow.number, 2, nextRow.number, worksheet.lastColumn!.number)
                                }

                            }
                        });
                        await saveWorkbookTo(workbook, `${data?.supplier?.name}采购单-${data?.submittedDateTime ?? data!.createdDateTime.format(DATE_WITH_TIME_FORMATER)}`)
                        setOpenExportColumnSelectModal(false)
                    }} onCancel={_ => setOpenExportColumnSelectModal(false)}/>

                </Col>
                {employeeAuthorizationStore.hasAuthority("采购_入库_入库")
                && !data?.receiptDateTime
                && !!data?.submittedDateTime ?
                    <Col>
                        <LoadableButton onClick={async (event) => {
                            event.stopPropagation()
                            let receiptId = (await receiptProcurement(id)).data;
                            setData({...data!, receiptDateTime: OffsetDateTime.now(), receiptId,})
                            navigate(`/procurements/receipts/${receiptId}`)
                        }}>入库</LoadableButton>
                    </Col> : undefined}
                {employeeAuthorizationStore.hasAuthority("采购_下单") && !data?.submittedDateTime &&
                    <Col>
                        <LoadableButton onClick={async (event) => {
                            event.stopPropagation()
                            await submitProcurement(id)
                            setData({...data!, submittedDateTime: OffsetDateTime.now()})
                        }}>
                            提交订单
                        </LoadableButton>
                    </Col>}
                {<Col>
                    <LoadableButton onClick={async (event) => {
                        // await submitProcurement(id)
                        // setData({...data!, submittedDateTime: OffsetDateTime.now()})
                    }}>
                        打印
                    </LoadableButton></Col>}
                <div style={{flexGrow: 1}}/>
                {employeeAuthorizationStore.hasAuthority("采购_入库_查询") && !!data?.receiptDateTime &&
                    <Link to={`/procurements/receipts/${data?.receiptId}`}>
                        <Button type={"link"}>查看入库单</Button>
                    </Link>}
                {employeeAuthorizationStore.hasAuthority("卖场_订单_下单") && <MarketSelectPopover onConfirm={async (v)=>{
                    let marketOrderId = (await convertProcurementToMarketOrder(id,v)).data;
                    navigate(`/markets/orders/${marketOrderId}`)
                }}>
                    <Button>生成卖场订单</Button>
                </MarketSelectPopover>}
            </Row>

            {!!data && ((employeeAuthorizationStore.hasAuthority("采购_修改") && !data?.submittedDateTime) && !data?.receiptDateTime) &&
                <EditOrderItemRow<EditOrderItemGoodsData & {
                    price: number
                }>
                    request={{}}
                    withAmount
                    withPrice
                    fetchGoods={async () => {
                        let response = await findAllGoodsWithHistoryProcurementSupplier(data!!.supplier.id);
                        return response.data.map(it => {
                            return {
                                ...it,
                                rememberedPrice: it.rememberedPurchasePrice,
                                units: it.units,
                            }
                        })
                    }}
                    optionRender={it => {
                        return <Space>
                            <span>{it.subGoods ? `${it.barcode}|${it.subGoods.number}` : it.barcode}</span>
                            <span>{it.subGoods ? it.subGoods.name + `（${it.name}）` : it.name}</span>
                            <span>￥{it.price}</span>
                        </Space>
                            ;
                    }}
                    onFinish={async (values) => {
                        let existed = amountAndUnitHistories?.find(it => it.goodsId === values.goodsId);
                        if (existed) {
                            myDatabase.goodsAmountAndUnitUseHistory.delete(existed.id!!)
                        }
                        myDatabase.goodsAmountAndUnitUseHistory.add({
                            scope: GoodsAmountAndUnitUseHistoryScope.PROCUREMENT,
                            resourceId: id,
                            amount: values.amount,
                            unitId: values.unitId,
                            goodsId: values.goodsId,
                            price: values.price,
                        })

                        return addProcurementItem(id, {...values, purchasePrice: values.price ?? 0}).then(() => {
                            query()
                        })
                    }}
                    availableAmountAndUnitHistories={amountAndUnitHistories}
                    existedGoodsKeys={data?.items?.map(it => ({goodsId: it.id, subGoodsId: it.subGoods?.id,})) ?? []}/>}
            <DataPageLayout leftActions={<>
            </>}>

                <GoodsTable<ProcurementItem> loading={loading}
                                             summary={tableSummaryGenerator}
                                             size={"small"}
                                             customColumns={columns => {
                                                 configSubGoodsColumns(columns)
                                                 ArrayUtils.insertAfter(columns, value => value.dataIndex === "name", {
                                                     dataIndex: "amountInOrder",
                                                     title: "数量与单位",
                                                     render: (value, record) => {
                                                         return <div>{value}{record.unit?.name}</div>
                                                     },
                                                     generateExcelValue: (value, record) => {
                                                         return `${value}${record.unit?.name ?? ""}`
                                                     }
                                                 },)
                                                 ArrayUtils.insertAfter(columns, value => value.dataIndex === "price", {
                                                     dataIndex: "purchasePrice",
                                                     title: "采购价",
                                                 },)
                                                 columns.push({
                                                     dataIndex: "note",
                                                     title: "备注",
                                                 })
                                                 columns.push({
                                                     ignoreInExcel: true,
                                                     title: "操作",
                                                     fixed: "right",
                                                     render: (_, item, index) => {
                                                         return <Space>
                                                             {employeeAuthorizationStore.hasAuthority("采购_修改") && !data?.receiptDateTime &&
                                                                 <EditAmountAndUnitPopover units={item.units}
                                                                                           initialData={{
                                                                                               amount: item.amountInOrder,
                                                                                               unitId: item.unit?.id,
                                                                                               price: item.purchasePrice,
                                                                                           }}
                                                                                           onConfirm={async value => {
                                                                                               if (item.subGoods) {
                                                                                                   await updateProcurementItemSubAmount(id, item.id, value, item.subGoods.id)
                                                                                               } else {
                                                                                                   await updateProcurementItemAmount(id, item.id, value)
                                                                                               }
                                                                                               const index = data!.items.indexOf(item)
                                                                                               let items = Array.from(data!.items ?? []);
                                                                                               items[index].amountInOrder = value.amount
                                                                                               items[index].unit = item.units.find(it => it.id === value.unitId)
                                                                                               setData({
                                                                                                   ...data!,
                                                                                                   items
                                                                                               })
                                                                                           }}
                                                                 >
                                                                     <Button type={"link"}
                                                                             onClick={event => event.stopPropagation()}>修改数量</Button>
                                                                 </EditAmountAndUnitPopover>}
                                                             {employeeAuthorizationStore.hasAuthority("采购_修改") &&
                                                                 <SingleInputPopover
                                                                     required
                                                                     initialValue={item.purchasePrice.toString()}
                                                                     title={"修改采购价"}
                                                                     customInput={(props, ref) => {
                                                                         return <Input ref={ref}
                                                                                       step={0.01}
                                                                                       type={"number"} {...props}/>
                                                                     }}
                                                                     onConfirm={async value => {
                                                                         const number = parseFloat(value)
                                                                         if (item.subGoods) {
                                                                             await updateProcurementItemSubPurchasePrice(id, item.id, number, item.subGoods.id)
                                                                         } else {
                                                                             await updateProcurementItemPurchasePrice(id, item.id, number)
                                                                         }
                                                                         const index = data!.items.indexOf(item)
                                                                         let items = Array.from(data!.items ?? []);
                                                                         items[index].purchasePrice = number
                                                                         setData({
                                                                             ...data!,
                                                                             items,
                                                                         })
                                                                     }}
                                                                     fieldName={"采购价"}>

                                                                     <Button type={"link"}
                                                                             onClick={(event) => {
                                                                                 event.stopPropagation()
                                                                             }}><EditOutlined/>修改采购价</Button>
                                                                 </SingleInputPopover>}
                                                             {employeeAuthorizationStore.hasAuthority("采购_修改") &&
                                                                 <SingleInputPopover initialValue={item.note}
                                                                                     title={"修改备注"}

                                                                                     onConfirm={async value => {
                                                                                         if (item.subGoods) {
                                                                                             await updateProcurementItemSubNote(id, item.id, value, item.subGoods.id)
                                                                                         } else {
                                                                                             await updateProcurementItemNote(id, item.id, value)
                                                                                         }
                                                                                         const index = data!.items.indexOf(item)
                                                                                         let items = Array.from(data!.items ?? []);
                                                                                         items[index].note = value
                                                                                         setData({
                                                                                             ...data!,
                                                                                             items,
                                                                                         })
                                                                                     }}
                                                                                     fieldName={"备注"}>

                                                                     <Button type={"link"}
                                                                             onClick={(event) => {
                                                                                 event.stopPropagation()
                                                                             }}><EditOutlined/>备注</Button>
                                                                 </SingleInputPopover>}

                                                             <AuthorizationResource
                                                                 authorities={["采购_修改"]}>
                                                                 <Button type={"link"}
                                                                         danger
                                                                         onClick={async (event) => {
                                                                             event.stopPropagation()
                                                                             if (item.subGoods) {
                                                                                 await deleteProcurementItemSub(id, item.id, item.subGoods.id)
                                                                             } else {
                                                                                 await deleteProcurementItem(id, item.id)
                                                                             }
                                                                             let items = Array.from(data!.items);
                                                                             ArrayUtils.remove(items, item)
                                                                             setData({
                                                                                 ...data!,
                                                                                 items
                                                                             })
                                                                         }}>
                                                                     <DeleteOutlined/>
                                                                     删除
                                                                 </Button>
                                                             </AuthorizationResource>
                                                         </Space>
                                                     }

                                                 },);
                                                 columnsRef.current = columns;
                                                 return columns;
                                             }}
                                             rowKey={(record, index) => {
                                                 return record.id.toString() + (record.subGoods?.id ?? "")
                                             }} data={Array.from(data?.items ?? [])}>
                </GoodsTable>
            </DataPageLayout>

        </>
    )
}

export default observerDashboardPageWrapper(ProcurementDetailPage, myPath, "采购单详情")

